﻿#include "pch.h"
#include "image.h"
#include <common/string.hpp>
#include <common/winapi.h>
#include <engine/renderd2d.h>
#include <common/memory.h>
#include <olectl.h>
#include <wrl/client.h>
#include <common/Exception.h>
#define ALPHA_TRANSPARENT	0x00			///<透明度：透明
#define ALPHA_OPAQUE		0xFF			///<透明度：不透明
#define ALPHA_HALF			0x80			///<透明度：半透明

namespace JOUI
{
	UIImage::UIImage(INT width, INT height)
	{
		//创建WIC位图
		throw_if_failed(
			g_wic_factory->CreateBitmap(
				width, height, GUID_WICPixelFormat32bppPBGRA,
				WICBitmapCacheOnDemand, &m_wic_bitmap),
			L"创建WIC位图失败"
		);
		//设置成员
		throw_if_failed(g_d2d_dc->CreateBitmapFromWicBitmap(m_wic_bitmap, &m_d2d_bitmap), L"创建图像文件解码器失败");
		m_cur_frame = 0;
		m_frame_count = 1;
		D2D1_SIZE_F SIZE = m_d2d_bitmap->GetSize();
		m_width = SIZE.width;
		m_height = SIZE.height;
	}

	LPSTREAM img_createfromstream_init(LPVOID data, size_t size)
	{
		if (size > 0)
		{
			LPVOID hMem = GlobalAlloc(GMEM_MOVEABLE, size);
			if (hMem != 0)
			{
				LPSTREAM lpStream = nullptr;
				throw_if_failed(CreateStreamOnHGlobal(hMem, TRUE, &lpStream), L"创建数据流失败");
				LPVOID lpMem = GlobalLock(hMem);
				if (lpMem != 0)
				{
					RtlMoveMemory(lpMem, data, size);
					GlobalUnlock(hMem);
					return lpStream;
				}
				GlobalFree(hMem);
			}
		}
		return NULL;
	}
	IWICBitmap* _wic_convert(IWICBitmapSource* pBitmapSource, BOOL bFreeOld)
	{
		INT nError = 0;
		IWICBitmap* pBitmapConvert = nullptr;
		IWICFormatConverter* pConverter = nullptr;
		nError = g_wic_factory->CreateFormatConverter(&pConverter);
		if (nError == 0)
		{
			nError = pConverter->Initialize(pBitmapSource, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.0, WICBitmapPaletteTypeCustom);
			if (nError == 0)
			{
				nError = g_wic_factory->CreateBitmapFromSource(pConverter, WICBitmapCacheOnDemand, &pBitmapConvert);
				if (nError == 0 && bFreeOld)
				{
					pBitmapSource->Release();
				}
			}
			pConverter->Release();
		}
		return pBitmapConvert;
	}
	IWICBitmap* _wic_selectactiveframe(IWICBitmapDecoder* pDecoder, INT nIndex, D2D1_RECT_F* dest)
	{
		INT nError = 0;
		IWICBitmap* ret = nullptr;
		IWICBitmapFrameDecode* pFrame = nullptr;
		nError = pDecoder->GetFrame(nIndex, &pFrame);
		if (pFrame)
		{
			ret = _wic_convert(pFrame, TRUE);
		}

		if (dest)
		{
			PROPVARIANT propValue;
			PropVariantInit(&propValue);
			IWICMetadataQueryReader* pFrameMetadataQueryReader = NULL;
			pFrame->GetMetadataQueryReader(&pFrameMetadataQueryReader);
			pFrameMetadataQueryReader->GetMetadataByName(L"/imgdesc/Left", &propValue);
			if (propValue.vt == VT_UI2)
			{
				dest->left = propValue.uiVal;
			}
			PropVariantClear(&propValue);
			PropVariantInit(&propValue);
			pFrameMetadataQueryReader->GetMetadataByName(L"/imgdesc/Top", &propValue);
			if (propValue.vt == VT_UI2)
			{
				dest->top = propValue.uiVal;
			}
			PropVariantClear(&propValue);
			PropVariantInit(&propValue);
			pFrameMetadataQueryReader->GetMetadataByName(L"/imgdesc/Width", &propValue);
			if (propValue.vt == VT_UI2)
			{
				dest->right = dest->left + propValue.uiVal;
			}
			PropVariantClear(&propValue);
			PropVariantInit(&propValue);
			pFrameMetadataQueryReader->GetMetadataByName(L"/imgdesc/Height", &propValue);
			if (propValue.vt == VT_UI2)
			{
				dest->bottom = dest->top + propValue.uiVal;
			}
			PropVariantClear(&propValue);
			pFrameMetadataQueryReader->Release();

		}

		return ret;
	}
	void UIImage::wic_init_from_decoder(IWICBitmapDecoder* pDecoder)
	{
		INT nError = S_FALSE;
		UINT pCount = 0;
		nError = pDecoder->GetFrameCount(&pCount);
		if (nError == S_OK)
		{
			m_wic_bitmap = _wic_selectactiveframe(pDecoder, 0, NULL);
			if (m_wic_bitmap)
			{
				m_cur_frame = 0;
				m_frame_count = pCount;
				//通过当前WIC位图创建D2D位图
				if (g_d2d_dc->CreateBitmapFromWicBitmap(m_wic_bitmap, &m_d2d_bitmap) == S_OK)
				{
					D2D1_SIZE_F SIZE = m_d2d_bitmap->GetSize();
					m_width = SIZE.width;
					m_height = SIZE.height;
					m_WicDecoder = pDecoder;
				}
			}
		}
	}
	UIImage::UIImage(LPCWSTR file)
	{
		try
		{
			IWICBitmapDecoder* decoder = nullptr;
			//解码图像
			throw_if_failed(
				g_wic_factory->CreateDecoderFromFilename(file,
					nullptr, GENERIC_READ,
					WICDecodeMetadataCacheOnLoad,
					&decoder
				), L"创建图像文件解码器失败"
			);
			wic_init_from_decoder(decoder);
		}catch_continue({});
	}
	UIImage::UIImage(HBITMAP hBitmap, HPALETTE hPalette, BOOL fPreAlpha)
	{
		try
		{
			//创建WIC位图
			throw_if_failed(
				g_wic_factory->CreateBitmapFromHBITMAP(hBitmap, hPalette,
					fPreAlpha ? WICBitmapAlphaChannelOption::WICBitmapUsePremultipliedAlpha : WICBitmapAlphaChannelOption::WICBitmapIgnoreAlpha, &m_wic_bitmap), L"创建WIC位图失败");

			throw_if_failed(g_d2d_dc->CreateBitmapFromWicBitmap(m_wic_bitmap, &m_d2d_bitmap), L"创建位图失败");
			m_cur_frame = 0;
			m_frame_count = 1;
			D2D1_SIZE_F SIZE = m_d2d_bitmap->GetSize();
			m_width = SIZE.width;
			m_height = SIZE.height;
		}catch_continue({});
	}
	UIImage::UIImage(HICON hIcon)
	{
		try
		{
			//通过HICON创建WIC位图
			IWICBitmap* wic_bitmap = nullptr;
			throw_if_failed(
				g_wic_factory->CreateBitmapFromHICON(hIcon, &wic_bitmap),
				L"创建WIC位图失败"
			);

			//创建像素格式转换器并初始化
			IWICFormatConverter* converter = nullptr;
			throw_if_failed(
				g_wic_factory->CreateFormatConverter(&converter),
				L"创建像素格式转换器失败"
			);
			throw_if_failed(
				converter->Initialize(wic_bitmap, GUID_WICPixelFormat32bppPBGRA,
					WICBitmapDitherTypeNone, nullptr, 0,
					WICBitmapPaletteTypeCustom
				), L"初始化像素格式转换器失败"
			);

			//创建符合像素格式要求的WIC位图
			throw_if_failed(
				g_wic_factory->CreateBitmapFromSource(converter,
					WICBitmapCacheOnDemand, &m_wic_bitmap),
				L"创建WIC位图对象失败"
			);
			wic_bitmap->Release();
			converter->Release();
			throw_if_failed(g_d2d_dc->CreateBitmapFromWicBitmap(m_wic_bitmap, &m_d2d_bitmap), L"创建位图失败");
			m_cur_frame = 0;
			m_frame_count = 1;
			D2D1_SIZE_F SIZE = m_d2d_bitmap->GetSize();
			m_width = SIZE.width;
			m_height = SIZE.height;
		}
		catch_continue({});
	}
	UIImage::UIImage(LPVOID data, size_t size)
	{
		wic_createfrommemory(data, size);
	}
	UIImage::UIImage(INT nWidth, INT nHeight, BYTE* pbBuffer)
	{
		wic_createfrompngbits(nWidth, nHeight, pbBuffer);
	}
	UIImage::UIImage(IWICBitmap* src_bitmap)
	{
		try
		{
			//创建像素格式转换器并初始化
			IWICFormatConverter* converter = nullptr;
			throw_if_failed(
				g_wic_factory->CreateFormatConverter(&converter),
				L"创建像素格式转换器失败"
			);
			throw_if_failed(
				converter->Initialize(src_bitmap, GUID_WICPixelFormat32bppPBGRA,
					WICBitmapDitherTypeNone, nullptr, 0,
					WICBitmapPaletteTypeCustom
				), L"初始化像素格式转换器失败"
			);

			//创建符合像素格式要求的WIC位图
			throw_if_failed(
				g_wic_factory->CreateBitmapFromSource(converter,
					WICBitmapCacheOnDemand, &m_wic_bitmap),
				L"创建WIC位图对象失败"
			);
			converter->Release();
			throw_if_failed(g_d2d_dc->CreateBitmapFromWicBitmap(m_wic_bitmap, &m_d2d_bitmap), L"创建位图失败");
			m_cur_frame = 0;
			m_frame_count = 1;
			D2D1_SIZE_F SIZE = m_d2d_bitmap->GetSize();
			m_width = SIZE.width;
			m_height = SIZE.height;
		}
		catch_continue({});
	}
	UIImage::UIImage(LPSTREAM lpStream)
	{
		wic_createfromstream(lpStream);
	}
	UIImage::UIImage(LPCWSTR ourcefile, BOOL fCode, UINT uiWidth, UINT uiHeight, UIColor color)
	{
		wic_createfromsvg(ourcefile, fCode, uiWidth, uiHeight, color);
	}
	UIImage::UIImage(UIZip* hRes, LPCWSTR fileName)
	{
		if (hRes)
		{
			DWORD unsize = 0;
			LPVOID buffer;
			hRes->ReadSource(fileName, &buffer, &unsize);
			if (unsize != 0)
				wic_createfrommemory(buffer, unsize);
		}
	}
	UIImage::~UIImage()
	{
		SafeRelease(m_d2d_bitmap);
		SafeRelease(m_wic_bitmap);
		SafeRelease(m_WicDecoder);
	}
	void UIImage::wic_drawframe(IWICBitmapSource* pFrame, D2D1_RECT_F* dest)
	{
		if (m_frame_count > 1)
		{
			D2D1_RENDER_TARGET_PROPERTIES rtp = D2D1::RenderTargetProperties(
				D2D1_RENDER_TARGET_TYPE_DEFAULT,
				D2D1::PixelFormat(
					DXGI_FORMAT_B8G8R8A8_UNORM,
					D2D1_ALPHA_MODE_PREMULTIPLIED),
				96.0f, // default dpi
				96.0f, // default dpi
				D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE);

			ID2D1RenderTarget* rt = nullptr;
			g_d2d_factory->CreateWicBitmapRenderTarget(m_wic_bitmap, &rtp, &rt);
			if (rt != 0)
			{
				rt->BeginDraw();
				ID2D1Bitmap* pBitmap = nullptr;
				rt->CreateBitmapFromWicBitmap(pFrame, NULL, &pBitmap);
				if (pBitmap != 0)
				{
					rt->DrawBitmap(pBitmap, dest, 1, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, NULL);
					pBitmap->Release();
				}
				rt->EndDraw();
				rt->Release();
			}
		}
	}
	void UIImage::wic_createfromstream(LPSTREAM lpStream)
	{
		IWICBitmapDecoder* pDecoder = nullptr;
		if (FAILED(g_wic_factory->CreateDecoderFromStream(lpStream, NULL, WICDecodeMetadataCacheOnDemand, &pDecoder))) return;
		wic_init_from_decoder(pDecoder);
	}
	void UIImage::wic_createfromsvg(LPCWSTR ourcefile, BOOL fCode, UINT uiWidth, UINT uiHeight, UIColor color)
	{
		throw_if_failed(
			g_wic_factory->CreateBitmap(uiWidth, uiHeight, GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &m_wic_bitmap), L"创建新WIC位图失败"
		);

		D2D1_RENDER_TARGET_PROPERTIES rtp = D2D1::RenderTargetProperties(
			D2D1_RENDER_TARGET_TYPE_DEFAULT,
			D2D1::PixelFormat(
				DXGI_FORMAT_B8G8R8A8_UNORM,
				D2D1_ALPHA_MODE_PREMULTIPLIED),
			96.0f, // default dpi
			96.0f, // default dpi
			D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE);
		Microsoft::WRL::ComPtr<ID2D1RenderTarget> pRT = nullptr;
		g_d2d_factory->CreateWicBitmapRenderTarget(m_wic_bitmap, &rtp, &pRT);
		if (pRT != 0)
		{
			ID2D1DeviceContext5* spDeviceContext5 = nullptr;
			pRT->QueryInterface(&spDeviceContext5);
			IStream* pstream = nullptr;
			IStream* ptemplate = nullptr;
			if (fCode)
			{
				std::vector<CHAR> ret = JOUI::ExString::w2c2(ourcefile);
				pstream = SHCreateMemStream(reinterpret_cast<const BYTE*>(ret.data()), ret.size());
			}
			else
			{
				throw_if_failed(SHCreateStreamOnFileEx(ourcefile, STGM_READ, 0, FALSE, ptemplate, &pstream), L"创建数据流失败"
				);
			}
			Microsoft::WRL::ComPtr<ID2D1SvgDocument> svgDocument = nullptr;
			spDeviceContext5->CreateSvgDocument(pstream, D2D1::SizeF(uiWidth, uiHeight), &svgDocument);

			if (!color.empty())
			{
				Microsoft::WRL::ComPtr<ID2D1SvgElement> svgelement = nullptr;
				svgDocument->GetRoot(&svgelement);
				if (svgelement->IsAttributeSpecified(L"fill"))
				{
					Microsoft::WRL::ComPtr<ID2D1SvgPaint> paint;
					svgelement->GetAttributeValue(L"fill", &paint);
					D2D1_SVG_PAINT_TYPE paintType = paint->GetPaintType();
					if (paintType == D2D1_SVG_PAINT_TYPE_COLOR)
					{
						// Retrieve the color of this paint.
						D2D1_COLOR_F oldColor;
						paint->GetColor(&oldColor);

						// If the old color not black, change it to newColor.
						if (oldColor.r != 0.0f || oldColor.g != 0.0f || oldColor.b != 0.0f)
						{
							// Attributes that are returned as an interface (such as ID2D1SvgPaint)
							// are returned by reference, rather than by value. This means that
							// modifying them (such as by calling SetColor, below) directly modifies
							// the SVG document, without needing to call SetAttributeValue.
							paint->SetColor(color.GetDxObject());
						}
					}
				}
			}

			spDeviceContext5->BeginDraw();
			spDeviceContext5->Clear();
			spDeviceContext5->DrawSvgDocument(svgDocument.Get());
			spDeviceContext5->EndDraw();

			throw_if_failed(g_d2d_dc->CreateBitmapFromWicBitmap(m_wic_bitmap, &m_d2d_bitmap), L"创建位图失败");
			m_wic_bitmap->GetSize(&m_width, &m_height);

			SafeRelease(pstream);
			SafeRelease(ptemplate);
			SafeRelease(spDeviceContext5);
		}
	}
	void UIImage::wic_createfrommemory(LPVOID data, size_t size)
	{
		//解码图像
		LPSTREAM lpStream = img_createfromstream_init(data, size);
		if (lpStream)
			wic_createfromstream(lpStream);
	}
	void UIImage::wic_createfrompngbits(INT nWidth, INT nHeight, BYTE* pbBuffer)
	{
		INT len = nWidth * nHeight * 4;
		//创建WIC位图
		throw_if_failed(
			g_wic_factory->CreateBitmapFromMemory(
				nWidth, nHeight, GUID_WICPixelFormat32bppPBGRA,
				nWidth * 4, len, pbBuffer, &m_wic_bitmap),
			L"创建WIC位图失败"
		);

		throw_if_failed(g_d2d_dc->CreateBitmapFromWicBitmap(m_wic_bitmap, &m_d2d_bitmap), L"创建位图失败");
		m_cur_frame = 0;
		m_frame_count = 1;
		m_width = nWidth;
		m_height = nHeight;
	}
	HANDLE UIImage::LoadFromMemoryHandle(LPVOID lpData, size_t dwLen, INT uType, INT nIndex)
	{
		HANDLE ret = 0;
		if (!IsBadReadPtr(lpData, dwLen))
		{
			LPVOID hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwLen);
			if (hMem)
			{
				LPVOID lpMem = GlobalLock(hMem);
				if (lpMem)
				{
					RtlMoveMemory(lpMem, lpData, dwLen);
					GlobalUnlock(hMem);
					if (uType == IMAGE_ICON || uType == IMAGE_CURSOR)
					{
						if (nIndex == 0)
							nIndex = 1;
						WORD s = ((ICONDIR*)lpData)->idCount;
						if (s >= nIndex)
						{
							short type = ((ICONDIR*)lpData)->idType;
							BOOL bIcon = (type == IMAGE_ICON);
							LPVOID offset = (LPVOID)((size_t)lpData + 6 + (nIndex - 1) * sizeof(ICONDIRENTRY));
							LPVOID tmp = lpMem;
							if (!bIcon)
							{
								__set_short(lpMem, 0, ((ICONDIRENTRY*)offset)->wBitCount);
								tmp = (LPVOID)((size_t)tmp + 4);
							}

							RtlMoveMemory(tmp, (LPVOID)((size_t)lpData + ((ICONDIRENTRY*)offset)->dwImageOffset), ((ICONDIRENTRY*)offset)->dwBytesInRes);
							CHAR b1 = ((ICONDIRENTRY*)offset)->bWidth;
							CHAR b2 = ((ICONDIRENTRY*)offset)->bHeight;
							HICON hicon = CreateIconFromResourceEx((PBYTE)lpMem, ((ICONDIRENTRY*)offset)->dwBytesInRes, bIcon, 196608, b1, b2, 0);
							ret = CopyImage(hicon, uType, 0, 0, 4);
						}
					}
					else
					{
						LPSTREAM lpStream;
						if (CreateStreamOnHGlobal(hMem, FALSE, &lpStream))
						{
							LPVOID lpObj = nullptr;
							if (OleLoadPicture(lpStream, (LONG)dwLen, TRUE, IID_IPicture, &lpObj) == 0)
							{
								OLE_HANDLE hImg = 0;
								((IPicture*)lpObj)->get_Handle(&hImg);
								SHORT objType = 0;
								((IPicture*)lpObj)->get_Type(&objType);
								if (objType == uType)
								{
									ret = CopyImage((HANDLE)hImg, uType, 0, 0, 4);
								}
								((IPicture*)lpObj)->Release();
							}
							lpStream->Release();
						}
					}
				}
				GlobalFree(hMem);
			}
		}
		return ret;
	}
	HRESULT UIImage::SetCurFrame(INT index)
	{
		if (m_frame_count > 1)
		{
			D2D1_RECT_F dest;
			IWICBitmap* pFrame = _wic_selectactiveframe(m_WicDecoder, index, &dest);
			
			if (pFrame != 0)
			{
				wic_drawframe(pFrame, &dest);
				m_d2d_bitmap->Release();
				throw_if_failed(g_d2d_dc->CreateBitmapFromWicBitmap(m_wic_bitmap, &m_d2d_bitmap), L"创建位图失败");
				pFrame->Release();
				m_cur_frame = index;
				return S_OK;
			}
		}
		return S_FALSE;
	}
	UINT UIImage::GetCurFrame()
	{
		return m_cur_frame;
	}
	UINT UIImage::GetFrameCount()
	{
		return m_frame_count;
	}
	HRESULT UIImage::GetSize(UINT& Width, UINT& Height)
	{
		Width = m_width;
		Height = m_height;
		return S_OK;
	}
	HRESULT UIImage::NextFrame(UINT* r_next_index, UINT* r_next_delay)
	{
		//单帧图像直接返回
		if (m_frame_count == 1) { return S_FALSE; }

		//获取下一帧索引
		UINT next_index = (m_cur_frame + 1) % m_frame_count;
		D2D1_RECT_F dest;
		IWICBitmap* pFrame = _wic_selectactiveframe(m_WicDecoder, next_index, &dest);

		if (pFrame != 0)
		{
			wic_drawframe(pFrame, &dest);
			pFrame->Release();
			m_cur_frame = next_index;
			if (r_next_index) { *r_next_index = next_index; }

			//获取下一帧延迟
			if (r_next_delay) 
			{ 
				INT nFrames = 0;
				GetFrameDelay(nFrames, next_index);
				*r_next_delay = nFrames;
			}

			return S_OK;
		}
		return S_FALSE;
	}
	BOOL UIImage::GetFrameDelay(INT& lpDelayAry, INT nFrames)
	{
		BOOL fOK = FALSE;
		if (m_WicDecoder)
		{
			IWICBitmapFrameDecode* pFrame = nullptr;
			HRESULT nError = m_WicDecoder->GetFrame(nFrames - 1, &pFrame);
			if (nError == S_OK)
			{
				IWICMetadataQueryReader* pReader = nullptr;
				nError = pFrame->GetMetadataQueryReader(&pReader);
				if (nError == S_OK)
				{
					PROPVARIANT pValue = {};
					nError = pReader->GetMetadataByName(L"/grctlext/Delay", &pValue);
					if (nError == S_OK)
					{
						USHORT nDelay = pValue.uiVal;
						if (nDelay == S_OK)
						{
							nDelay = 10;
						}
						lpDelayAry = nDelay;
						fOK = TRUE;
					}
					pReader->Release();
				}
				pFrame->Release();
			}
		}
		return fOK;
	}
	HRESULT UIImage::GetPixel(INT x, INT y, UIColor& r_color)
	{
		CHECK_PARAM(x < (INT)m_width && y < (INT)m_height);
		WICRect rcl = { x, y, 1, 1 };
		COLORREF ret = 0; HRESULT hr = S_FALSE;
		if (m_wic_bitmap)
		{
			hr = m_wic_bitmap->CopyPixels(&rcl, 4, 4, (BYTE*)&ret);
			r_color = UIColor(ret);
		}
		return hr;
	}
	HRESULT UIImage::SetPixel(INT x, INT y, UIColor color)
	{
		CHECK_PARAM(x < (INT)m_width && y < (INT)m_height);
		info_bitmapdata *pBitmapData = nullptr;
		RECT rect1 = { x, y, 1, 1 };
		if (Lock(&rect1, WICBitmapLockRead | WICBitmapLockWrite, 2498570, &pBitmapData) == S_OK) //PixelFormat32bppARGB
		{
			BYTE* pByte = new BYTE[4];
			if (pBitmapData->scan0 != 0)
			{
				for (int i = 0; i < 4; i++)
				{
					pByte[i] = (BYTE)(color.GetRGB() >> 8 * (3 - i) & 0xff);
				}
				pBitmapData->scan0 = pByte;
			}
			UnLock(pBitmapData);
			delete[] pByte;
			delete pBitmapData;
		}
		return S_OK;
	}
	HRESULT UIImage::Copy(UIImage** r_dest, RECT* copy_rect)
	{
		CHECK_PARAM(r_dest);
		CHECK_PARAM(m_wic_bitmap);

		//计算复制区域
		WICRect rc = { 0, 0, (INT)m_width, (INT)m_height };
		if (copy_rect)
		{
			rc.X = copy_rect->left;
			rc.Y = copy_rect->top;
			rc.Width = copy_rect->right - copy_rect->left;
			rc.Height = copy_rect->bottom - copy_rect->top;
		}
		//创建一个新的WIC位图
		IWICBitmap* new_bitmap = nullptr;
		handle_if_failed(
			g_wic_factory->CreateBitmapFromSourceRect(
				m_wic_bitmap, rc.X, rc.Y, rc.Width, rc.Height, &new_bitmap
			), L"创建新WIC位图失败"
		);
		auto pImg = new UIImage();
		throw_if_failed(g_d2d_dc->CreateBitmapFromWicBitmap(new_bitmap, &pImg->m_d2d_bitmap), L"创建位图失败");
		pImg->m_cur_frame = 0;
		pImg->m_wic_bitmap = new_bitmap;
		pImg->m_width = m_width;
		pImg->m_height = m_height;
		*r_dest = pImg;
		return S_OK;
	}
	HRESULT UIImage::Scale(UINT new_width, UINT new_height, UIImage** r_dest, RECT* copy_rect)
	{
		CHECK_PARAM(r_dest);
		CHECK_PARAM(new_width > 0 && new_height > 0);
		CHECK_PARAM(m_wic_bitmap);
		//计算复制区域
		WICRect rc = { 0, 0, (INT)m_width, (INT)m_height };
		if (copy_rect)
		{
			rc.X = copy_rect->left;
			rc.Y = copy_rect->top;
			rc.Width = copy_rect->right - copy_rect->left;
			rc.Height = copy_rect->bottom - copy_rect->top;
		}

		D2D1_BITMAP_PROPERTIES bp = D2D1::BitmapProperties(
			D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED)
		);

		//创建一个WIC位图缩放器
		IWICBitmapScaler* scaler = nullptr;
		handle_if_failed(
			g_wic_factory->CreateBitmapScaler(&scaler),
			L"创建WIC位图缩放器失败"
		);

		//初始化WIC位图缩放器
		handle_if_failed(
			scaler->Initialize(m_wic_bitmap, new_width, new_height, WICBitmapInterpolationModeFant),
			L"初始化WIC位图缩放器失败"
		);
		
		//创建一个新的WIC位图
		IWICBitmap* new_bitmap = nullptr;
		handle_if_failed(
			g_wic_factory->CreateBitmapFromSourceRect(
				scaler, rc.X, rc.Y, rc.Width, rc.Height, &new_bitmap
			), L"创建新WIC位图失败"
		);
		scaler->Release();
		auto pImg = new UIImage();
		throw_if_failed(g_d2d_dc->CreateBitmapFromWicBitmap(new_bitmap, &pImg->m_d2d_bitmap), L"创建位图失败");
		pImg->m_cur_frame = 0;
		pImg->m_wic_bitmap = new_bitmap;
		pImg->m_width = m_width;
		pImg->m_height = m_height;
		*r_dest = pImg;
		return S_OK;
	}
	BOOL UIImage::Rotateflip(INT rfType, UIImage** r_dest)
	{
		CHECK_PARAM(m_wic_bitmap);
		IWICBitmapSource* pBitmapSource = m_wic_bitmap;
		IWICBitmapFlipRotator* pBitmapFlipRotator = nullptr;
		g_wic_factory->CreateBitmapFlipRotator(&pBitmapFlipRotator);
		if (pBitmapFlipRotator)
		{
			HRESULT hr = pBitmapFlipRotator->Initialize(pBitmapSource, (WICBitmapTransformOptions)rfType);
			if (hr == S_OK)
			{
				auto pImg = new UIImage();
				throw_if_failed(g_d2d_dc->CreateBitmapFromWicBitmap(pBitmapFlipRotator, &pImg->m_d2d_bitmap), L"创建位图失败");
				pImg->m_cur_frame = 0;
				pImg->m_wic_bitmap = (IWICBitmap*)pBitmapFlipRotator;
				pImg->m_width = m_width;
				pImg->m_height = m_height;
				*r_dest = pImg;
				return TRUE;
			}
		}
		return FALSE;
	}
	LPVOID UIImage::GetContext()
	{
		return m_d2d_bitmap;
	}
	GUID _wic_GetContainerFormatFromFormat(int format)
	{
		static const std::map<int, GUID> formatMap = {
			{1, GUID_ContainerFormatJpeg},
			{2, GUID_ContainerFormatBmp},
			{3, GUID_ContainerFormatIco},
			{4, GUID_ContainerFormatTiff},
			{5, GUID_ContainerFormatGif},
			{6, GUID_ContainerFormatWmp},
			{7, GUID_ContainerFormatDds},
			{8, GUID_ContainerFormatAdng},
			{9, GUID_ContainerFormatWebp},
			{10, GUID_ContainerFormatHeif}
		};

		auto it = formatMap.find(format);
		if (it != formatMap.end())
		{
			return it->second;
		}
		return GUID_ContainerFormatPng; // 默认返回 PNG 格式
	}
	BOOL _wic_savetobin(BOOL IsFile, LPCWSTR wzFileName, IWICBitmapSource* pBitmapSource, LPVOID& lpBin, size_t& len, INT format)
	{
		HRESULT hr = S_OK;
		LPSTREAM pStream = nullptr;
		IWICStream* pIWICStream = nullptr;
		IWICBitmapEncoder* pEncoder = nullptr;
		IWICBitmapFrameEncode* pFrame = nullptr;
	cleanup:
		// 释放资源
		if (pFrame) pFrame->Release();
		if (pEncoder) pEncoder->Release();
		if (pIWICStream) pIWICStream->Release();
		if (pStream) pStream->Release();


		hr = CreateStreamOnHGlobal(NULL, FALSE, &pStream);
		if (FAILED(hr)) return FALSE;

		UINT width, height;
		hr = pBitmapSource->GetSize(&width, &height);
		if (FAILED(hr)) goto cleanup;

		hr = g_wic_factory->CreateStream(&pIWICStream);
		if (FAILED(hr)) goto cleanup;

		hr = IsFile ? pIWICStream->InitializeFromFilename(wzFileName, GENERIC_WRITE) : pIWICStream->InitializeFromIStream(pStream);
		if (FAILED(hr)) goto cleanup;

		GUID iformat = _wic_GetContainerFormatFromFormat(format);
		hr = g_wic_factory->CreateEncoder(iformat, nullptr, &pEncoder);
		if (FAILED(hr)) goto cleanup;

		hr = pEncoder->Initialize(IsFile ? pIWICStream : pStream, WICBitmapEncoderNoCache);
		if (FAILED(hr)) goto cleanup;

		hr = pEncoder->CreateNewFrame(&pFrame, nullptr);
		if (FAILED(hr)) goto cleanup;

		hr = pFrame->Initialize(nullptr);
		if (FAILED(hr)) goto cleanup;

		hr = pFrame->SetSize(width, height);
		if (FAILED(hr)) goto cleanup;

		WICPixelFormatGUID aa = GUID_WICPixelFormatDontCare;
		hr = pFrame->SetPixelFormat(&aa);
		if (FAILED(hr)) goto cleanup;

		hr = pFrame->WriteSource(pBitmapSource, nullptr);
		if (FAILED(hr)) goto cleanup;

		hr = pFrame->Commit();
		if (FAILED(hr)) goto cleanup;

		hr = pEncoder->Commit();
		if (FAILED(hr)) goto cleanup;
	
		// 仅当不保存到文件时，才从内存流提取数据
		if (!IsFile)
		{
			LPVOID hMem = nullptr;
			hr = GetHGlobalFromStream(pStream, &hMem);
			if (FAILED(hr)) goto cleanup;

			LPVOID pData = GlobalLock(hMem);
			if (pData != nullptr)
			{
				len = GlobalSize(hMem);
				lpBin = ExMemReAlloc(lpBin, len);
				RtlMoveMemory(lpBin, pData, len);
				GlobalUnlock(hMem);
			}
			GlobalFree(hMem);
		}
		return hr == S_OK;
	}

	BOOL UIImage::Save(LPVOID& lpBuffer, size_t& len, INT format)
	{
		CHECK_PARAM_RET(m_wic_bitmap, FALSE);
		IWICBitmapSource* pBitmapSource = m_wic_bitmap;
		return _wic_savetobin(FALSE, NULL, pBitmapSource, lpBuffer, len, format);
	}
	BOOL UIImage::Save(LPCWSTR wzFileName, INT format)
	{
		CHECK_PARAM_RET(m_wic_bitmap, FALSE); LPVOID lpBuffer = 0; size_t len = 0;
		IWICBitmapSource* pBitmapSource = m_wic_bitmap;
		return _wic_savetobin(TRUE, wzFileName, pBitmapSource, lpBuffer, len, format);
	}
	HRESULT UIImage::Lock(RECT* lpRectL, DWORD flags, INT PixelFormat, info_bitmapdata** lpLockedBitmapData)
	{
		CHECK_PARAM(m_wic_bitmap);
		INT nError = 0;
		IWICBitmap* pBitmapSource = m_wic_bitmap;
		UINT swidth, sheight;
		INT width, height, left, top;
		nError = pBitmapSource->GetSize(&swidth, &sheight);
		if (nError == 0)
		{
			if (lpRectL == 0 || IsBadReadPtr(lpRectL, 16))
			{
				left = 0;
				top = 0;
				width = swidth;
				height = sheight;
			}
			else
			{
				left = lpRectL->left;
				top = lpRectL->top;
				width = lpRectL->right;
				height = lpRectL->bottom;
			}
			IWICBitmapLock* pLock = NULL;
			WICRect rc{ left, top, width, height };
			nError = pBitmapSource->Lock(&rc, flags, &pLock);
			if (nError == 0)
			{
				UINT stride;
				nError = pLock->GetStride(&stride);
				if (nError == 0)
				{
					UINT dwlen = 0;
					BYTE* scan0 = 0;
					nError = pLock->GetDataPointer(&dwlen, &scan0);
					if (nError == 0)
					{
						auto BitmapData = new info_bitmapdata();
						BitmapData->width = width;
						BitmapData->height = height;
						BitmapData->pixelFormat = PixelFormat;
						BitmapData->stride = stride;
						BitmapData->scan0 = scan0;
						BitmapData->reserved = pLock;
						*lpLockedBitmapData = BitmapData;
					}
				}
				if (nError != 0)
				{
					pLock->Release();
				}
			}
		}
		return S_OK;
	}
	HRESULT UIImage::UnLock(info_bitmapdata* lpLockedBitmapData)
	{
		CHECK_PARAM(lpLockedBitmapData);
		if (lpLockedBitmapData->reserved != nullptr)
		{
			((IWICBitmapLock*)lpLockedBitmapData->reserved)->Release();
			lpLockedBitmapData->reserved = nullptr;
			return S_OK;
		}
		return S_FALSE;
	}
	
}


